define(function(require, exports) {
	var $ = require('jquery');
	var pubjs = require('pubjs');
	var util = require('util');
	var view  = require('@base/view');
	var raphael = require('@libs/raphael/raphael.2.2.1.js');

	// 游戏创意编辑窗口 - 关系管理模块
	var Base = view.container.extend({
		init: function(config) {
			var self = this;
			config = pubjs.conf(config, {
				'class': 'M-PageRelation',
				'item_height': 121,
				'height': 900,
				// 圈圈属性
				'radius': 25,
				'stroke_width': 3,
				'stroke_color': '#999',
				'background': '#fff',
				// 连接线属性
				'line_attr': {
					"stroke": '#999',
					"stroke-width": 3,
					"stroke-linecap": "round"
				},
				// 活动类型 1 RTB 2代理 3直投，4移动
				'channelType': 1,
				'offset': 4
			});


			self.$left = [];
			self.$right = [];

			self.Super('init', arguments);
		},
		afterBuild: function() {
			var self = this;
			var el = self.getDOM();
			var c = self.getConfig();
			var doms = self.$doms = {};

			doms.head = $('<div class="M-PageRelationHead"/>').appendTo(el);
			doms.body = $('<div class="M-PageRelationBody"/>').appendTo(el);

			if (c.channelType == 1){

				doms.linktip = $('<div class="M-PageRelationTip"/>').appendTo(el);
				$('<div/>').html(LANG('可拖拽节点关联前后端创意。<br>未关联落地页的前端创意包，将由系统自动将其与所有落地页进行关联！')).appendTo(doms.linktip);

				//创建'不再提醒'复选框
				doms.notRemind  = $('<div class="notRemind"/>').appendTo(doms.linktip);
				doms.checkbox = $('<input type="checkbox" />').appendTo(doms.notRemind);
				$('<span />').text(LANG('不再提醒')).appendTo(doms.notRemind);

				var btn = $('<input type="button" class="btn btn-default"/>').val(LANG('知道了')).appendTo(doms.linktip);
				self.uiBind(btn, 'click', 'eventClickTip');
			}

			self.$papaer = raphael(doms.body.get(0), '100%', c.height);

			self.$rightSet = self.$papaer.set();
			self.$rightPos = 0;
			self.$leftSet = self.$papaer.set();
			self.$leftPos = 0;


			self.$deleteTip = self.$papaer.add([
				{
					type: 'rect',
					x: -40,
					y: -30,
					width: 80,
					height: 20,
					r: 4,
					'stroke': '#ccc',
					'stroke-width': 2,
					'fill': '#EDB1B1'
				},
				{
					type: 'text',
					text: LANG('双击删除'),
					x: -26,
					y: -8,
					fill: '#fff',
					'text-anchor': 'start',
					'font-size': 14,
					'font-weight': 300
				}
			]);
			self.$deleteTip.transform('t-100,-100');
			this.$adType = 0;
		},
		/**
		 * 重置模块数据
		 * @return {None} 无返回
		 */
		reset: function(){
			var self = this;
			// 删除左边的节点
			util.each(self.$left, function(item){
				item.holder.remove();
				item.mask.remove();
				item.trigger.remove();
				item.text.remove();
				util.each(item.lines, function(link){
					link.line.remove();
					link.line = null;
				});
			});
			self.$leftSet.clear();
			// this.$leftPos = 0;
			self.$left.splice(0, self.$left.length);

			// 删除右边的节点
			util.each(self.$right, function(item){
				item.holder.remove();
				item.mask.remove();
				item.trigger.remove();
				item.text.remove();
				util.each(item.lines, function(link){
					if (link.line) {link.line.remove();}
				});
			});
			self.$rightSet.clear();
			// this.$rightPos = 0;
			self.$right.splice(0, self.$right.length);

			// 隐藏提示标签
			// self.$deleteTip.hide();
			self.$showTip = true;

			if (self.$doms.linktip) {
				self.$doms.linktip.hide();
			}

			return self;
		},
		/**
		 * 设置关系数据
		 * @param {Object} data ID关系数据
		 */
		setData: function(data, type){
			var self = this;

			self.reset();
			// 添加左节点
			util.each(data.left, function(left_id){
				self.add(left_id, 'left');
			});
			// 添加右节点
			util.each(data.right, function(right_id){
				self.add(right_id, 'right');
			});
			// 添加链接
			util.each(data.link, function(rights, left_id){
				util.each(rights, function(right_id){
					self.addLink(+left_id, right_id);
				});
			});

			self.$adType = type;
		},
		/**
		 * 获取关系数据
		 * @return {Object} 返回ID关系数据对象
		 */
		getData: function(){
			var result = {};
			var rights = [];
			var empty_right = [];
			var hasEmpty = false;
			var autoLink = !!this.$doms.linktip;

			if (this.$adType != 2){
				if (autoLink){
					util.each(this.$right, function(right){
						rights.push(right.id);
						if (util.first(right.lines) === undefined){
							empty_right.push(right.id);
							hasEmpty = true;
						}
					});
				}

				util.each(this.$left, function(left){
					var list = [];
					util.each(left.lines, function(link, right_id){
						list.push(+right_id);
					});

					if (autoLink){
						if (list.length){
							list.push.apply(list, empty_right);
							result[left.id] = list;
						}else {
							result[left.id] = rights;
							hasEmpty = true;
						}
					}else {
						result[left.id] = list;
					}
					list = null;
				});
			}
			if (hasEmpty && !confirm(LANG('尚有创意包或者落地页没有建立任何关系, 要自动建立关系吗?'))){
				return false;
			}

			return result;
		},
		/**
		 * 添加链接点
		 * @param {Number} id   链接点ID
		 * @param {String} side 添加位置, left - 左边, right - 右边
		 * @return {Object} 返回记录项目
		 */
		add: function(id, side){

			var item, list;
			side = (side == 'left');
			list = (side ? this.$left : this.$right);
			// 检查是否已经存在同一个ID记录
			item = util.find(list, id, 'id');
			if (item){
				return item;
			}

			var c = this.getConfig();
			var x, y, dr, set, pos;
			if (side){
				set = this.$leftSet;
				x = c.radius + c.stroke_width/2 + c.offset;
				dr = c.radius;
				pos = this.$leftPos;
			}else {
				set = this.$rightSet
				x = this.$doms.body.width() - c.radius - c.stroke_width/2 - c.offset;
				dr = -c.radius;
				pos = this.$rightPos;
			}
			y = list.length * c.item_height + c.item_height / 2;

			// 建立节点圈圈
			var big = this.$papaer.circle(x, y, c.radius);
			big.attr({
				"stroke": c.stroke_color,
				"stroke-width": c.stroke_width,
				"fill": c.background
			});
			var small = this.$papaer.circle(x + dr, y, c.radius / 5);
			small.attr({
				"stroke-width": 0,
				"fill": c.stroke_color
			});
			var num = this.$papaer.text(x, y, list.length + 1);
			num.attr({
				"fill": c.stroke_color,
				'font-size': c.radius * 1.2,
				'font-weight': 600,
				'cursor': 'default'
			});

			var mask = this.$papaer.circle(x, y, c.radius*1.2 );
			mask.attr({
				'fill': '#fff',
				'stroke-width': 0,
				'opacity': 0,
				'cursor':'pointer'
			}).data('index', id);

			// 绑定事件
			mask.drag(this.dragMove, this.dragStart, this.dragEnd, this, this, this);
			set.push(big, small, num, mask);
			this.$deleteTip.toFront();
			big.transform('t0,'+pos);
			small.transform('t0,'+pos);
			num.transform('t0,'+pos);
			mask.transform('t0,'+pos);

			item = {
				id: id,
				holder: big,
				trigger: small,
				text: num,
				mask: mask,
				posY: y,
				lines: {}
			};
			list.push(item);

			//从cookies读值，判断是否有勾选‘不再提醒’选项
			var notRemind = util.cookie('notRemind');
			if(!notRemind){
				// 左右都添加了项目时, 显示提示
				if (this.$left.length && this.$right.length && this.$showTip){
					this.$showTip = false;
					if (this.$doms.linktip) {this.$doms.linktip.show();}
				}
			}

			// 代理活动时, 自动添加连线
			if (c.channelType == 2){
				util.each(this.$left, function(left){
					util.each(this.$right, function(right){
						this.addLink(left.id, right.id);
					}, this);
				}, this);
			}
			return item;
		},
		/**
		 * 删除链接点
		 * @param  {Number} id   要删除的链接点ID
		 * @param  {String} side 删除的位置, left - 左边, right - 右边
		 * @return {Bool}      返回删除状态
		 */
		remove: function(id, side){
			var c = this.getConfig();
			side = (side == 'left');
			var list = side ? this.$left : this.$right;
			var set  = side ? this.$leftSet : this.$rightSet

			// 删除对应的链接
			if (side){
				this.removeLink(id, 0);
			}else {
				this.removeLink(0, id);
			}

			// 删除节点
			var len=list.length, dy=0, item, y;
			function update_link(link){
				if (side){
					link.path[1] -= dy;
					link.path[3] -= dy;
				}else {
					link.path[5] -= dy;
					link.path[7] -= dy;
				}
				this.setLine(link.line, link.path);
			}
			for (var i=0; i<list.length; i++){
				item = list[i];
				if (item.id == id){
					list.splice(i,1);
					set.exclude(item.holder);
					item.holder.remove();
					set.exclude(item.trigger);
					item.trigger.remove();
					set.exclude(item.text);
					item.text.remove();
					set.exclude(item.mask);
					item.mask.remove();
					dy += c.item_height;
					i--;
				}else if (dy){
					item.posY -= dy;
					y = item.posY;
					item.holder.attr('cy', y);
					item.trigger.attr('cy', y);
					item.mask.attr('cy', y);
					item.text.attr('y', y);
					item.text.attr('text', i+1);

					// 同步修改连线坐标
					util.each(item.lines, update_link, this);
				}
			}
			return (len - i);
		},
		/**
		 * 删除关系链接
		 * @param  {Number} left_id  左边节点的节点ID
		 * @param  {Number} right_id 右边节点的节点ID
		 * @return {None}          无返回
		 */
		removeLink: function(left_id, right_id){
			// 删除左边的节点
			if (right_id){
				util.each(this.$left, function(item){
					if ((!left_id || item.id == left_id) && item.lines[right_id]){
						var link = item.lines[right_id];
						if (link.line){
							link.line.remove();
							link.line = null;
						}
						item.lines[right_id] = null;
						delete(item.lines[right_id]);
					}
				});
			}

			// 删除右边的节点
			if (left_id){
				util.each(this.$right, function(item){
					if ((!right_id || item.id == right_id) && item.lines[left_id]){
						var link = item.lines[left_id];
						if (link.line){
							link.line.remove();
							link.line = null;
						}
						item.lines[left_id] = null;
						delete(item.lines[left_id]);
					}
				});
			}

			this.$deleteTip.hide();
		},
		/**
		 * 添加关系连接
		 * @param {Number} left_id  左边关联ID
		 * @param {Number} right_id 右边关联ID
		 */
		addLink: function(left_id, right_id){
			var c = this.getConfig();
			var left = util.find(this.$left, left_id, 'id');
			var right = util.find(this.$right, right_id, 'id');

			if (!left || !right){
				return false;
			}
			if (left.lines[right_id] && right.lines[left_id]){
				// 已经存在该关系
				return true;
			}

			var xl = left.trigger.attr('cx');
			var yl = left.posY + this.$leftPos;
			var xr = right.trigger.attr('cx');
			var yr = right.posY + this.$rightPos;
			var xm = this.$doms.body.width() / 2;

			var link = {
				path: [xl,yl,xm,yl,xm,yr,xr,yr],
				line: this.$papaer.path('M0,0'),
				left_pos: this.$leftPos,
				right_pos: this.$rightPos
			};
			this.setLine(link.line, link.path);

			link.line.toBack();
			link.line.hover(this.lineEvent, this.lineEvent, this, this);
			link.line.mousemove(this.lineEvent, this);
			link.line.dblclick(this.lineEvent, this);
			link.line.mousedown(this.noEvent);
			link.line.attr(c.line_attr);
			link.line.attr('cursor', 'pointer')
			link.line.data('left', left_id);
			link.line.data('right', right_id);

			left.lines[right_id] = link;
			right.lines[left_id] = link;

			// 有关联存在, 移除提示信息
			if (this.$doms.linktip) { this.$doms.linktip.hide(); }
		},
		/**
		 * 设置滚动位置
		 * @param  {String} side 要滚动的位置, left - 左边, right - 右边
		 * @param  {Number} pos  滚动的偏移位置
		 * @return {None}      无返回
		 */
		scroll: function(side, pos){
			switch(side){
				case 'left':
					this.$leftPos = pos;
				break;
				case 'right':
					this.$rightPos = pos;
				break;
				default:
					return false;
			}
			this.doScroll(side);
			return true;
		},
		/**
		 * 滚动功能执行函数 <私有> 更新链接线的位置
		 * @param  {String} side 要滚动的位置, left - 左边, right - 右边
		 * @return {None}      无返回
		 */
		doScroll: function(side){
			side = (side == 'left');
			var set = side ? this.$leftSet : this.$rightSet
			var pos = side ? this.$leftPos : this.$rightPos;
			var list = side ? this.$left : this.$right;

			set.transform('t0,'+pos);

			// 更新线条位置
			util.each(list, function(item){
				util.each(item.lines, function(link){
					var dpos;
					if (side){
						dpos = pos - link.left_pos;
						link.left_pos = pos;
						link.path[1] += dpos;
						link.path[3] += dpos;
					}else {
						dpos = pos - link.right_pos;
						link.right_pos = pos;
						link.path[5] += dpos;
						link.path[7] += dpos;
					}
					this.setLine(link.line, link.path);
				},this);
			},this);
		},
		/**
		 * <私有> 更新连接线的绘图位置
		 * @param {Object} line 要更新的线条对象
		 * @param {Array} p    要更新的线条参数
		 */
		setLine: function(line, p){
			var path = 'M'+p[0]+','+p[1]+'C'+p[2]+','+p[3]+','+p[4]+','+p[5]+','+p[6]+','+p[7];
			line.attr('path', path);
		},
		/**
		 * <私有> 拖动头线段跟随图像位置
		 * @param  {Number} x 相对画布的绝对X位置坐标
		 * @param  {Number} y 相对画布的绝对Y位置坐标
		 * @return {None}   无返回
		 */
		updateLine: function(x, y){
			var i = this.$dragInfo;
			i.elm.attr('cx', x);
			i.elm.attr('cy', y - i.item_pos);
			i.path[2] = (x + i.x)/2;
			i.path[4] = i.path[2];
			i.path[5] = y;
			i.path[6] = x;
			i.path[7] = y;
			this.setLine(i.line, i.path);
		},
		/**
		 * 关联点拖动事件处理函数
		 */
		dragStart: function(x, y, evt){
			var c = this.getConfig();

			if (this.$dragInfo){
				return false;
			}
			var elm = this.$papaer.getByTarget(evt.target);
			var side = elm.attr('cx') > this.$doms.body.width()/2;
			var index = elm.data('index');
			var item = util.find(side ? this.$right : this.$left, index, 'id');
			var pos = side ? this.$rightPos : this.$leftPos;

			if (!item) { return false; }
			var point = item.trigger;
			var offset = this.$doms.body.offset();

			var i = this.$dragInfo = {
				elm: point.toFront(),
				line: this.$papaer.path('M0,0'),
				path: null,
				item: item,
				item_pos: pos,
				target: null,
				target_pos: (side ? this.$leftPos : this.$rightPos),
				x: point.attr('cx'),
				y: point.attr('cy') + pos,
				dx: evt.pageX - offset.left,
				dy: evt.pageY - offset.top,
				side: side
			};
			i.path = [i.x, i.y, i.x, i.y, i.x, i.y, i.x, i.y];
			i.line.attr(c.line_attr);
			item.lines.drag = {
				path: i.path,
				line: i.line,
				left_pos: this.$leftPos,
				right_pos: this.$rightPos
			};

			this.updateLine(i.dx, i.dy);

			// 开始拖动, 移除提示框
			if (this.$doms.linktip) { this.$doms.linktip.hide(); }
		},
		dragMove: function(dx, dy){
			var i = this.$dragInfo;
			var c = this.getConfig();

			if (!i){ return false; }

			var x = i.dx + dx, y = i.dy + dy;
			if (!i.target){
				this.updateLine(x,y);
			}

			var inx = i.side ? x: this.$doms.body.width() - x;
			inx = (inx > c.offset && inx < c.offset + 2 * (c.radius + c.stroke_width));
			var iny = (y - i.target_pos) % c.item_height;
			iny = (iny > c.item_height/2 - c.radius && iny < c.item_height/2 + c.radius);
			i.target = null;

			if (inx && iny){
				inx = Math.floor((y-i.target_pos)/c.item_height);
				iny = i.side ? this.$left : this.$right;
				if (iny[inx]){
					var item = iny[inx];
					if (!i.target || i.target !== item){
						i.target = item;
						x = item.holder.attr('cx') + (i.side ? c.radius : -c.radius);
						this.updateLine(x, item.holder.attr('cy') + i.target_pos);
					}
				}
			}
		},
		dragEnd: function(){
			var i = this.$dragInfo;
			this.$dragInfo = null;
			i.elm.attr('cx', i.x);
			i.elm.attr('cy', i.y - i.item_pos);
			i.item.mask.toFront();

			if (i.target && !i.target.lines[i.item.id] && !i.item.lines[i.target.id]){
				// 有目标, 建立联系
				// 绑定线条事件
				i.line.toBack();
				i.line.hover(this.lineEvent, this.lineEvent, this, this);
				i.line.mousemove(this.lineEvent, this);
				i.line.dblclick(this.lineEvent, this);
				i.line.mousedown(this.noEvent);
				i.line.attr('cursor', 'pointer')
				i.line.data('left', i.side ? i.target.id : i.item.id);
				i.line.data('right', i.side ? i.item.id : i.target.id);

				var link = i.item.lines.drag;
				i.item.lines[i.target.id] = link;
				i.target.lines[i.item.id] = link;

				if (i.side){
					// 右边拖拽，交换坐标点
					link = link.path;
					var j = link[0];
					link[0] = link[6]; link[6] = j;
					j = link[1];
					link[1] = link[3] = link[7];
					link[5] = link[7] = j;
				}
			}else {
				i.line.remove();
			}
			// 没有目标，或者关系已存在，删除连接
			i.item.lines.drag = null;
			delete(i.item.lines.drag);
		},
		/**
		 * 连线操作事件处理函数
		 * @param  {[type]} evt [description]
		 * @return {[type]}     [description]
		 */
		lineEvent: function(evt){
			var c = this.getConfig();

			if (this.$dragInfo || c.channelType == 2){
				return false;
			}
			var line = this.$papaer.getByTarget(evt.target);
			if (!line){
				return false;
			}
			var tip = this.$deleteTip;
			switch (evt.type){
				case 'mousemove':
					tip.animate({'transform': 't'+evt.offsetX+','+evt.offsetY}, 100);
				break;
				case 'mouseover':
					tip.transform('t'+evt.offsetX+','+evt.offsetY).show();
					line.attr({
						"stroke": '#f00',
						"stroke-width": 5
					});
				break;
				case 'mouseout':
					line.attr(c.line_attr);
					tip.hide();
				break;
				case 'dblclick':
					this.removeLink(line.data('left'), line.data('right'));
				return false;
			}
		},
		/**
		 * 线条鼠标事件拦截函数
		 */
		noEvent: function(evt){
			if (evt.preventDefault) {evt.preventDefault();}
			evt.cancelBubble = true;
			return false;
		},
		eventClickTip: function(evt){
			//若勾选了‘不再提醒’，则设置cookies
			if($(this.$doms.checkbox).prop("checked")){
				util.cookie("notRemind",true,365);
			}
			this.$doms.linktip.hide();
		}
	});

	exports.base = Base;
});
